videojs在play.asp使用过程中的坑

video.js在使用过程中遇到的一些问题

2017.9.21 四 16:20

A videojs documention

https://github.com/videojs/video.js/
$_BLOB: videojs文档

B videojs和play.asp

0 控制:jQuery VS vjs

  • vjs有自己的组件,事件,方法等,和jQ的性质差不多;既然是用vjs,就尽量用vjs的方法操作,API也方便(使用中发现,有优点,有缺点:页面加载完之前,是不到jQ对象的)。

  • vjs的setTimeout ,requestAnimation等方法

  • 优点中,当然包括方便的video API ,DOM操作

1 多语言

  1. 当时自己的多语言有点问题,==》用了vjs的多语言;
    还有些通过.el()添加的dom(速度、质量等把一个vjs组件的子元素重写了),并不会引vjs用多语言,就借了其他的块相同vjs组件。

  2. 后来发现,多语言要提交给三方翻译,其他地方也要用。基于同一的理念,弃用了vjs的多语言

2 组件

  1. vjs有很多组件,在写menu,subtitle,quality,rate时,考虑要不要重新注册vjs组 件。
    基于上面的元素有一些不确定性(字幕,质量等的多少没法控制,后面使用起来估计也不方便),既然有现成的,就还是用vjs的组件的,方便。

  2. 后来,准备控制条的tips时也准备注册组件,因为原生的title点击后会重新出现,而且 有些tips的内容有些许出入。
    看了,vjs的源码,通过源码的比对,在js中重新夺回了控制权。

  3. menu,subtitle,quality,rate等的添加,增加了许多判断:div_index,control-bar-hold,tips,menu….

  4. controlBar在点击的时候,是否需要保持,出现状态。
    tips在移动设备上不需要出现。

后来又做到注释—-多了组件,和前面几个menu_**是不一样的风格,考虑是不是样式/设计不用vjs的,写html的时候可以用原生、jQuery或者其他的库,只是单纯的引用vjs的API

3 事件

  1. 勾子函数没有一次用上的

  2. 和dashjs一起使用,mediaplay的事件监听收到限制,需要提前注册

  3. 由于以上两条:本地记录播放质量,字幕等时,在播放之前就设置有点困难。
    所以,选择了监听player的播放事件。(只有速度成功了;字幕取不到,质量无法设置)。

C 坑(issues)

0 vjs 基础

  1. 只有controls,才可以绑定video上 播放/暂停 事件

  2. 用js设置video宽高video1.style.height='260px',会阻止,video的全屏

    videojs/video.js/issues/1293

  3. tap、click事件及冒泡问题

  4. palyer的useractive()事件,会触发控制条出现,但随后会消失:即使移除了,vjs的vjs-user-inactive样式,其他vjs的操作,又会对useractive 重新负值。。

    ==》自定义了arv-controlBar-hold

  5. 同上面一样,自定义了arv-tip-enabled
    播放/暂停
    移动的tap和阻止事件冒泡
  6. 没有animate函数(jQuery),有requestAnimationFrame(fn),和cancel
  7. 重新定义的setTimeout,setInterval
  8. ios音量组件的考虑
  9. 移动端好像,监测不到video的事件video.width(),video.currentTime(),同样的pc就没有问题。最后都改成player的事件(4674)

ModalDialog

ModalDialog 使用出现问题:不能定义content中的内容;description 是在原有的基础加了test,而不是单独的test

\4463

1
2
3
4
5
6
7
8
9
10
11
12
13
var modal_content = '<div id="do-this">do this</div> <div id="do-that">do that</div>';
// where the magic happens
var contentEl = document.createElement('div');
// probably better to just build the entire thing via DOM methods
contentEl.innerHTML = modal_content;
var ModalDialog = videojs.getComponent('ModalDialog');
var modal = new ModalDialog(player, {
content: contentEl,
temporary: false
});

// $_sel
arv_title.contentEl().innerHTML='<b>sdfs</b>sdfs';

1 player没有tap事件

sol:绑定div_video,自定义tap

//自定义tap
$$(document).on("touchstart", function(e) {
    if(!$$(e.target).hasClass("disable"))  
    $$>e.target).data("isMoved", 0);
});
$$(document).on("touchmove", function(e) {
    if(!$$(e.target).hasClass("disable")) 
    $$(e.target).data("isMoved", 1);
});
$$(document).on("touchend", function(e) {
    if(!$$(e.target).hasClass("disable") && $$(e.target).data("isMoved") == 0) 
    $$(e.target).trigger("tap");
});

2 事件冒泡

  • click: BUTTON,会; MENUITEM、 PROGRESS-CONTROL不会
  • tap:都冒泡

sol: e.target==this

3 player tap事件,在iPad中

  • \

    #1886 2015.2.26: Unfortunately, this is how the video element works as well. Disabling controls also disables click events, so if you want to set something like this up you’ll need to add click event handlers to the Videojs element.

  • 自定义tap,在iPad中还会触发click,其他移动设备(包括iPhone)没有这种现象
    sol:e.preventDefault();

扩展:根据解释,只有video标签 controls才能触发click等事件;而且其上的一些其他元素的事件都不能触发,只会触发video标签的
#642 2013.7.16: Yes, this is an iOS issue. VideoJS on iOS falls back to the native controls.
If the native controls on iOS are enabled, iOS will not let anyone listen to any events in the area above the video element.
You could remove the ‘controls’ attribute of the video element whenever you want to listen to click events and then put it back when you’re done.

4 IOS中出现的问题

4.1 不能播放dash,包括用了dashjs

4.2 双控制条

sol:

  1. css

    video::-webkit-media-controls-panel-container {
      display: none !important;
    }
    video::-webkit-media-controls-start-playback-button {
      display:none !important;
      -webkit-appearance: none;
    }
    
  2. js:

    html5:{
            nativeControlsForTouch: false
    },
    
  3. 标签属性:

    playsinline
    

4.3 网页开始自动播放

设置autoplay并不会自动播放
sol: 还要加 muted(根据video标签的某个使用规则)

#1364
#337:I am not sure how autoplay is working on an iPhone unless you’re testing with an old version of iOS (pre-6.1). Apple disables autoplay and preload on iOS:

In Safari on iOS (for all devices, including iPad), where the user may be on a cellular network and be charged per data unit, preload and autoplay are disabled. No data is loaded until the user initiates it. This means the JavaScript play() and load() methods are also inactive until the user initiates playback, unless the play() or load() method is triggered by user action. In other words, a user-initiated Play button works, but an onLoad=”play()” event does not.
Sorry, it’s not possible.

4.4 点击开始播放自动进入全屏

sol: 上面的标签属性playsinline可以解决(好像要IOS10 及以上)

#3761,#896

4.5 音量控制

  • ios中音量不能通过编程控制,所以就隐藏了(包括在iPhone中)

    #562 2013.6.5:the iPad does not allow us to change volume programmatically, so, the decision was made to just hide the volume control altogether on the iPad and other devices where programmatic volume control is not allowed.

  • 那些不支持的就自动隐藏了

    #149 2012.12.21:It would be nice if video.js automatically hid the volume/mute controls for iOS and Chrome/Android users as they are not operational.

    #336

    #347

  • 考虑,用原生的

    #164 2012.4.5: I’ve been considering switching to use the iPads native controls instead, because custom controls are pretty limited. I’ll try to get that into the next release.

4.6 IOS中的音量控制:静音可以控制,但是volemeControl看不见

  • 有人提出静音是可以控制的
    sol:

    .video-js .vjs-volume-panel { display: flex !important; }
    .video-js .vjs-mute-control { display: inline-block !important; }
    
  • 但是volemeControl看不见
    sol: 自己又重写了css,并从dom中移除

    //js
    arvplayer.controlBar.volumePanel.volumeControl.hide();
    arvplayer.controlBar.volumePanel.addClass('noVolumeContr');
    //css
    .video-js .vjs-volume-panel.noVolCont.vjs-volume-panel-horizontal.vjs-slider-active,   
    .video-js .vjs-volume-panel.noVolCont.vjs-volume-panel-horizontal:active,   
    .video-js .vjs-volume-panel.noVolCont.vjs-volume-panel-horizontal:focus,   
    .video-js .vjs-volume-panel.noVolCont.vjs-volume-panel-horizontal:hover{
        width:4em;
    }
    

2017.9.21 四 19:09

6 结合dashjs

  1. 应用dashjs API player.dash.mediaPlayer.setQualityFor('video', 2)

    Questions work with dashjs

  2. 初始化的过程中有时候会报错

    Failed to set the ‘duration’ property on ‘MediaSource’: The MediaSource’s readyState is not ‘open’. #1349

  3. ios 中 不能播放的资源 会提示出现,但视频照常播放

    /videojs/videojs-contrib-dash/issues/211

  4. dashjs 的mediaplay的事件监听受到限制,需要在player初始化之前注册

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    videojs.Html5DashJS.hook('beforeinitialize', myCustomCallback);
    var myCustomCallback = function(arvplayer, mediaPlayer) {
    if (videojs && videojs.log) {
    mediaPlayer.getDebug().setLogToBrowserConsole(false);
    mediaPlayer.on('log', function(event) {
    // videojs.log(event.message);
    });
    }
    mediaPlayer.on('qualityChangeRendered',function(e){//auto 下检测初始质量及变化
    ddmp('mediaplayer on qulitychange rendered ...');
    ddmp(e);
    var i=e.newQuality;
    //dlog(this)// window
    if(mediaPlayer.getAutoSwitchQualityFor('video')){
    arv_menu_quality.$$('span')[1].innerHTML=ga_player_lang[15]+' <span>'+ga_dash_mp4[i].split(",")[1]+'p</span> >';
    }
    });
    };
  5. dash文件和mp4断网,重连后的恢复,稍微有些差别 断网重连

7 操作系统差异

7.1 移动端

  1. 所有移动设备中音量控制条,并不会随设备的音量键的变化而改变
  2. 移动设备监听不到video的属性和方法,都换成了playervjs 基础:列表8
  3. 移动端,监听indexImage change调用事件时,不明白为什么要用定时器
  4. 一直不能autoplay。除非muted。 auto play

7.2 macos

  1. macos safari,播放dash,.8上会出错(81是正常的),dashjs播放:列表3

7.3 windows

windows safari 已经放弃支持了

  1. windows safari,不支持h5播放;用vjs-falsh,报错

8 字幕位置的诡异

(4674)

  1. 第一条字幕(0:00)有时候出现,而且位置不确定
  2. 控制条出现后会覆盖现有字幕,下一条字幕会出现在控制条上方,控制条消失后会下降
  3. 时机:loaded

    I need event for subtitles loaded!

IOS原生字幕渲染 20180927

mp4文件中有字幕,和.vtt/.srt中的字幕是两回事。chrome中显示正常,不会显示两条字幕,单独播放mp4文件也没有字幕

  1. 第一条原生的字幕(和remote text track不一样)会显示,有时候还会显示两条字幕:原生和remote textTrack:
    在loadedMetaData中 一段时间内,频繁 删除原生 tract(在video中) 节点,因为不能确定时机。
  2. 在Mac OS 中字幕位置上下轮流切换:在css中用 !import写死位置

9 断网重连

issues:

  1. mobile和dash(1450)没有监测到错误。(5089)
  2. ie和chrome监测到的错误代码不一样;
  3. vjs-hls更新后,dahs和mp4的表现不一样

    Retry after network error

player error event doesn’t fire and not same on different brower

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
   function onError(e){
dvjs(arvplayer.error());
var time=arvplayer.currentTime();

switch(arvplayer.error().code){
//\\case 1: arvplayer.error(null).pause().load().currentTime(time).play();break;
case 1: console.error('tfdeu seems have debug ',e);break;
case 3: console.error('decode error');//break; //Edge浏览器报3,
case 2:
console.error('net error;arvplayer timer: ',arvplayerTimer);
// arvplayer.error(null); //null 虽然可以取消打叉,但是定时器无法一直触发
// arvplayer.pause();
if(arvplayerTimer){
return;
}
isArvplayerReload=true; // 立即显示黑屏,onseeking 需要判断
document.getElementById('load_video').style.display = 'block';
arvplayerTimer=arvplayer.setInterval(function(){
dplay('arvplayer restart ...');
// document.getElementById('load_video').style.display = 'block';

// FIXME: when replay if reconnect network, div_video click propgate:won't control video play/pause
arvplayer.load();// it's no influence on dash,but **required for mp4**
// if it is mp4, will replay video all the time when disconnect network
// **for dash, it should reload the source**
if(arvplayerCurrentSource.type=='application/dash+xml'){
arvplayer.src(arvplayerCurrentSource);
}
arvplayer.currentTime(time);
arvplayer.play();// if reconnect netwrok, **replay auto**
// dplay(arvplayer.error())//不行
},3000);
break;
case 4: console.error('can\'t play this video');break;
}
//\\ onSeeked();
}

function onPlaying(){
dvjs('on playing ...');
if(arvplayerTimer){
arvplayer.clearInterval(arvplayerTimer);
arvplayerTimer=null;
document.getElementById('load_video').style.display = 'none';
isArvplayerReload=false;
}
}
function onLoadeddata(){
//\\ document.getElementById('load_video').style.display = 'none';
if(!isArvplayerReload){//\\
document.getElementById('load_video').style.display = 'none';
}
}
function onSeeked(){
if(!isArvplayerReload){
document.getElementById('load_video').style.display = 'none';
}
}

其他参考:player_api.reset().src({type: 'application/x-mpegURL', src: String(play_path), withCredentials: false});

How to reload or replay the video.(In case of Error)

0 custom error messages

  1. arvplayer.error(null); errorDisplay: false

    Error message with the big X

  2. Otherwise you can override the text by setting a new “English” translation

    Question: how to customize media error messages without plugins

0 autoplay policy

不同浏览器的autoplay policy不一样,尤其是chrome(5160)。
移动设备,一直是禁止的。
静音可行,没试过
080530: chrome PC promise下面的代码没有进入/执行;移动端就没事。 sol:把loadeddata在ready触发,不进行判断了

  1. 直播的时候,没有触发onlodeadmetadata事件。

    loadedmetadata didn’t fire and not autoplay when cross origin

  2. 直播的时候,原生的和库(can-auto-play)监测到的promise是相反的;
    检测到false的时候,依然可以自动播放。
    点播没有上面提到的问题。

下面均在player的ready事件中绑定

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// studio
arvplayer.play();
var promise = video1.play();
if (promise !== undefined) {
promise.then(function() {
// Autoplay started!
}).catch(function(error) {
// Autoplay was prevented.
arv_bigPlayButton.show();
});
}else{
//console.log('autoplay==undefined');
}

// live
var promise = Video1.play();
if (promise !== undefined) {
promise.then(function() {
// Autoplay started!
video1.play();
}).catch(function(error) {
// Autoplay was prevented.
onLoadeddata();
if(video1.paused()){
arv_bigPlayButton.show();
}
try{// 实际可以播放,但catch
video1.play();
if(!video1.paused()){
arvfadeOut();
}
}catch(e){
console.warn('real catch error',e);
}
});
}else{
console.log('autoplay==undefined');
}

Autoplay Policy Changes

Autoplay Best Practices with Video.js

其它参考:

Autoplay is not working with desktop chrome v66

How to handle “Uncaught (in promise) DOMException: play() failed because the user didn’t interact with the document first.” on Desktop with Chrome 66?
回答1不清楚;回答2,浏览器配置 Chrome://flags

1 poster

  1. chrome中 object-fit 适应问题
    object-fit:fill | contain | cover | none | scale-down
    object-fit主要适合于替换元素,比如:<video>、<object>、<img>、<input type="image">、<svg>、<svg:image>、<svg:video> 等。其默认值为fill。
    参考:[Html5的video标签自动填充满父div的大小]

默认为:contain。但是chrome中显示不稳定,别人电脑为fill。清空缓存并硬性重载(只有控制台打开状态才有),就正常了。

属于chrome的bug:
[Chrome bug with CSS3 object-fit/object-position]//github.com/Fyrd/caniuse/issues/3169
Responsive object-fit: cover fix on Chrome
.. and so on

  1. audio only的时候,手机端,开始是暂停的话可以看到poster;点击播放后就是黑色。pc 正常。ios没有测试 /Fyrd/caniuse/issues/3169

2

knowledge is no pay,reward is kindness
0%